2009/04/16

Recent entries from same category

  1. PerlでWindowsと親和性の高いreadlineが欲しい → あった「Caroline」
  2. Perl をゆるふわと語ろう
  3. cpanfile とは何か、なぜそれを使いたいのか
  4. plackup の --path 引数
  5. Github Notification API が出たので通知を Growl するの書いた。

SQLite便利!
SQLite3におけるREGEXP演算子 - anon_193の日記

SQLite では、load_extension 関数を用いて、外部の拡張モジュールをロードすることが出来る。拡張モジュールは、いわばユーザ関数ライブラリで、SQLite3 ODBC Driver には標準で BLOB二次元マッピング拡張(sqlite3_mod_blobtoxy.dll)、外部データ取込・出力拡張(sqlite3_mod_impexp.dll)、全文検索拡張(sqlite3_mod_fts3.dll) が付属している。これらと同様にして、正規表現マッチングを行う regexp ユーザ関数を持つ拡張モジュールを制作し、ロードすれば、お目当ての REGEXP 演算子が使えるわけだ。

http://d.hatena.ne.jp/anon_193/20090114/1231935112
sqlite3_mod_regexp.cxx
#include <boost/regex.hpp>
#include <sqlite3ext.h>
extern "C" {
    SQLITE_EXTENSION_INIT1
    static void regexp_func(sqlite3_context *context, int argc, sqlite3_value **argv) {
        if (argc >= 2) {
            const char *target  = (const char *)sqlite3_value_text(argv[1]);
            const char *pattern = (const char *)sqlite3_value_text(argv[0]);
            try {
                boost::regex ereg(pattern, boost::regex_constants::perl);
                sqlite3_result_int(context, boost::regex_search(target, ereg));
            } catch (boost::regex_error &e) {
                sqlite3_result_error(context, e.what(), 0);
            }
        }
    }
    __declspec(dllexport) int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api) {
        SQLITE_EXTENSION_INIT2(api);
        return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, (void*)db, regexp_func, NULL, NULL);
    }
}
VCでコンパイルしました。
# cl /EHsc -Isrc -I. -I "c:\boost_1_35_0" sqlite3_mod_regexp.cxx /LD "C:\boost_1_35_0\libs\regex\build\vc80\libboost_regex-vc80-mt-s-1_35.lib"
サンプルデータ
foo.sql
CREATE TABLE foo(id integer primary key, value text);
INSERT INTO "foo" VALUES(1,'abc');
INSERT INTO "foo" VALUES(2,'def');
INSERT INTO "foo" VALUES(3,'あいうえお');
INSERT INTO "foo" VALUES(4,'かきくけこ');
INSERT INTO "foo" VALUES(5,'さしすせそ');
utf-8で保存して下さい
# cat foo.sql | sqlite3 foo.db
そしてPerlのコード
use strict;
use warnings;
use utf8;
use YAML;
use DBIx::Simple;

my $db = DBIx::Simple->connect("dbi:SQLite:dbname=c:/foo.db", "", "")
    or die DBIx::Simple->error;

$db->func(1, "enable_load_extension");

my $result = $db->query("select load_extension('/sqlite3_mod_regexp.dll')")
    or die DBIx::Simple->error;
warn Dump $db->query("select * from foo where value regexp '^[あか]'")->hashes;
dbのパスとdllのパスは指定して下さい
実行すると...
---
id: 3
value: あいうえお
---
id: 4
value: かきくけこ
スゲーーーー便利!
Posted at by